import java.io.File
import java.util.Locale

import scopt.OParser

import scala.xml.XML
import implicits.Implicits._
import org.joda.time.DateTime
import tool.Tool

/**
 * Created by yz on 6/7/2020
 */

case class Config(inDir: File = new File("."), outDir: File = new File("."))

object Main {

  def main(args: Array[String]): Unit = {

    val builder = OParser.builder[Config]
    val parser1 = {
      import builder._
      OParser.sequence(
        programName("scopt"),
        head("scopt", "4.x"),
        opt[File]('i', "inDir").valueName("<file>").action { (x, c) =>
          c.copy(inDir = x)
        }.text("please input  directory that only contains xml file!").required(),
        opt[File]('o', "outDir").valueName("<file>").action { (x, c) =>
          c.copy(outDir = x)
        }.text("please assign output directory!").required(),
        help("help").text("prints this usage text")
      )
    }
    OParser.parse(parser1, args, Config()) match {
      case Some(config) => exec(config)
      case _ =>
    }

  }

  def exec(config: Config) = {
    val dir = config.inDir
    val outDir = config.outDir
    dir.myListFiles.foreach { xmlFile =>
      println(s"${xmlFile.getName} is converting...")
      val datFile = new File(outDir, s"${xmlFile.namePrefix}.dat")
      xml2Dat(xmlFile, datFile)
    }
    println(s"convert finished!")
  }

  def xml2Dat(xmlFile: File, datFile: File) = {
    val xml = XML.loadFile(xmlFile)
    val headers =
      s"""
         |1.0
         |1
         |IMPORT
         |srclab
         |destlab
         |""".stripMargin.toLines
    val now = new DateTime()
    val time = now.toString("dd-MMM-yyyy HH:mm:ss", Locale.US)
    val hour = now.toString("HH:mm:ss.S", Locale.US)
    val content1s =
      s"""
         |AB
         |GeneMapper ID-X
         |""".stripMargin.toLines
    val strGenoTypeDataMap = Tool.produceStrGenotypeDataMap(xmlFile)
    val snpGenoTypeDataMap = Tool.produceSnpGenotypeDataMap(xmlFile)
    val basics = produceBasicDatas(xmlFile)
    val sampleNum = strGenoTypeDataMap.size
    val geneoTypeDataMap = strGenoTypeDataMap.zip(snpGenoTypeDataMap).map { case (strMap, snpMap) =>
      val id = strMap._1
      val genoTypes = (strMap._2 ++ snpMap._2)
      (id, genoTypes)
    }
    val basicMap = basics.map { basic =>
      (basic.id, basic)
    }.toMap
    val sampleContents = geneoTypeDataMap.flatMap { case (id, genotypeDatas) =>
      val headers =
        s"""
           |DNA Analysis Result
           |1.0
           |PCR
           |${basicMap(id).name}
           |0
           |Suspect, Known
           |unspecified
           |unspecified
           |unspecified
           |${genotypeDatas.size}
           |""".stripMargin.toLines
      val genotypeInfos = genotypeDatas.flatMap { genotypeData =>
        val siteName = genotypeData.locus
        val genotypes = genotypeData.genoType.mySplit(",").notEmptyLines
        if (genotypes.size >= 3) {
          println(id, siteName)
        }
        val infos =
          s"""
             |${siteName}
             |1
             |gmidx
             |${time}
             |${hour}
             |${genotypes.size}
             |""".stripMargin.toLines
        infos ::: genotypes
      }
      headers ::: genotypeInfos
    }.toList
    val newLines = headers ::: List(time) ::: content1s ::: List(sampleNum.toString) ::: sampleContents
    newLines.notEmptyLines.toFile(datFile)
  }

  case class BasicData(id: String, lane: String, gener: String, kind: String, name: String)

  def produceBasicDatas(file: File) = {
    val xml = XML.loadFile(file)
    (xml \\ "sample").toList.map { sampleNode =>
      val id = Tool.parseGetId(sampleNode)
      val gender = (sampleNode \ "basicInfo" \ "gender").text
      val kind = (sampleNode \ "basicInfo" \ "type").text
      val lane = (sampleNode \ "basicInfo" \ "lane").text
      val name = (sampleNode \ "basicInfo" \ "name").text
      BasicData(id, lane, gender, kind, name)
    }
  }


}
